package com.easylinkin.linkappapi.childinspection.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.childinspection.entity.InspectionQrCodeEntity;
import com.easylinkin.linkappapi.childinspection.entity.QrCodeRecordEntity;
import com.easylinkin.linkappapi.childinspection.mapper.InspectionPointMapper;
import com.easylinkin.linkappapi.childinspection.mapper.InspectionQrCodeMapper;
import com.easylinkin.linkappapi.childinspection.mapper.QrCodeRecordMapper;
import com.easylinkin.linkappapi.childinspection.service.InspectionQrCodeService;
import com.easylinkin.linkappapi.childinspection.vo.BaseVo;
import com.easylinkin.linkappapi.childinspection.vo.InspectionQrCodeVo;
import com.easylinkin.linkappapi.childinspection.vo.RelationVo;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.common.service.OSSServiceImpl;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author linWenLe
 * @Date: 2024/3/27
 * @Description:
 */
@Slf4j
@Service("inspectionQrCodeService")
public class InspectionQrCodeServiceImpl extends ServiceImpl<InspectionQrCodeMapper, InspectionQrCodeEntity> implements InspectionQrCodeService {

    @Resource
    LinkappUserContextProducer linkappUserContextProducer;

    @Resource
    private InspectionQrCodeMapper inspectionQrCodeMapper;

    @Resource
    private InspectionPointMapper inspectionPointMapper;

    @Resource
    private QrCodeRecordMapper qrCodeRecordMapper;

    @Resource
    private OSSServiceImpl ossService;

    public static final String INSPECTION_POINT_CODE = "EWMBH";

    @Override
    public IPage<InspectionQrCodeEntity> getList(RequestModel<InspectionQrCodeVo> restPage) {
        Page page = restPage.getPage();
        return inspectionQrCodeMapper.getList(page, restPage.getCustomQueryParams());
    }


    @Override
    public String createCode() {
        String inspectionPointCode = inspectionQrCodeMapper.selectMaxCode();
        if (inspectionPointCode == null){
            return INSPECTION_POINT_CODE + "0001";
        }
        Pattern pattern = Pattern.compile("\\d+(\\.\\d+)?");
        Matcher matcher = pattern.matcher(inspectionPointCode);
        int number = 0;
        while (matcher.find()) {
            number = Integer.parseInt(matcher.group()) + 1;
        }
        int length = 4; // 指定字符串的长度
        return INSPECTION_POINT_CODE + String.format("%0" + length + "d", number);
    }

    @Override
    @Transactional
    public void insert(InspectionQrCodeVo entityVo) {
        Assert.notNull(entityVo.getCode(), "二维码编码不能为空");
        LambdaQueryWrapper<InspectionQrCodeEntity> wrapper = Wrappers.lambdaQuery();
        List<InspectionQrCodeEntity> codeList = inspectionQrCodeMapper.selectList(wrapper.eq(InspectionQrCodeEntity::getCode, entityVo.getCode()));
        if (codeList.size() > 0){
            throw new RuntimeException("二维码编码已存在");
        }
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        InspectionQrCodeEntity entity = new InspectionQrCodeEntity();
        BeanUtils.copyProperties(entityVo,entity);
        String uuid = UUID.randomUUID().toString();
        entity.setId(uuid);
        entity.setCreateTime(new Date());
        entity.setCreator(tenantId);
        entity.setTenantId(tenantId);
        entity.setStatus(0);
        RelationVo vo = new RelationVo(uuid, entityVo.getCode(), null, null, 0);
        //添加使用记录
        inspectionQrCodeMapper.insertQrCodeRecord(vo);
        //添加巡检点
        inspectionQrCodeMapper.insert(entity);
        //生成二维码
        try {
            ByteArrayInputStream inputStream = this.generateQRCode(entity.getId());
            String url = ossService.uploadImg(inputStream, entity.getCode(), null);
            entity.setImageUrl(url);
            inspectionQrCodeMapper.update(entity, wrapper.eq(InspectionQrCodeEntity::getId, entity.getId()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    // 生成QR码的方法
    public ByteArrayInputStream generateQRCode(String data) {
        int width = 300;
        int height = 300;
        ByteArrayInputStream inputStream = null;
        try {
            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 设置字符编码
            hints.put(EncodeHintType.ERROR_CORRECTION, com.google.zxing.qrcode.decoder.ErrorCorrectionLevel.H); // 错误纠正级别
            hints.put(EncodeHintType.MARGIN, 1); // 边距
            MultiFormatWriter writer = new MultiFormatWriter();
            BitMatrix bitMatrix = writer.encode(data, BarcodeFormat.QR_CODE, width, height, hints);
            // 创建BufferedImage对象来表示QR码
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    image.setRGB(x, y, bitMatrix.get(x, y) ? Color.BLACK.getRGB() : Color.WHITE.getRGB());
                }
            }
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(image, "png", outputStream); // 将BufferedImage转换为JPEG格式的文件流
            byte[] byteArray = outputStream.toByteArray();
            inputStream = new ByteArrayInputStream(byteArray);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return inputStream;
    }

    @Override
    @Transactional
    public void update(InspectionQrCodeEntity entity) {
        entity.setModifyTime(new Date());
        entity.setModifier(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        inspectionQrCodeMapper.updateById(entity);
    }

    @Override
    @Transactional
    public void delete(String id) {
        inspectionQrCodeMapper.deleteById(id);
    }


    /**
     * 二维码关联巡检点位
     * @param relationVo
     */
    @Override
    @Transactional
    public void relationPoint(RelationVo relationVo) {
        //修改巡检点绑定的二维码
        inspectionPointMapper.updateByQrCode(relationVo);
        //清除二维码绑定的巡检点
        inspectionQrCodeMapper.cleanRelation(relationVo);
        //根据巡检点id修改结束时间
        inspectionQrCodeMapper.updateQrCodeRecordByPointId(relationVo.getInspectionPointId());
        //修改原有二维码使用记录
        inspectionQrCodeMapper.updateQrCodeRecord(relationVo);
        //新增二维码使用记录
        relationVo.setStatus(1);
        inspectionQrCodeMapper.insertQrCodeRecord(relationVo);
        //二维码关联巡检点
        inspectionQrCodeMapper.updateRelation(relationVo);
        //巡检点绑定二维码
        inspectionPointMapper.updatePointByQrCode(relationVo);
    }

    @Override
    public IPage<InspectionQrCodeEntity> getUseList(RequestModel<BaseVo> restPage) {
        Page page = restPage.getPage();
        BaseVo model = restPage.getCustomQueryParams();
        return qrCodeRecordMapper.selectRecordInfoList(page, model);
    }

    @Override
    public void relieve(RelationVo relationVo) {
        //清除原有关联关系
        inspectionQrCodeMapper.cleanRelation(relationVo);
        //根据巡检点id修改结束时间
        inspectionQrCodeMapper.updateQrCodeRecordByPointId(relationVo.getInspectionPointId());
        //修改二维码使用记录
        inspectionQrCodeMapper.updateQrCodeRecord(relationVo);
    }

    @Override
    public InspectionQrCodeEntity getQrCodeInfo(String id) {
        InspectionQrCodeEntity codeEntity = inspectionQrCodeMapper.selectById(id);
        LambdaQueryWrapper<QrCodeRecordEntity> wrapper = Wrappers.lambdaQuery();
        codeEntity.setCount(qrCodeRecordMapper.selectCount(wrapper.eq(QrCodeRecordEntity::getCode, codeEntity.getCode())));
        return codeEntity;
    }

}
